package com.base.lock.db;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.base.entity.Order;
import com.base.mapper.OrderMapper;
import com.base.mapper.ProductMapper;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class DBService {

	@Autowired
	private OrderMapper orderMapper;
	@Autowired
	private ProductMapper productMapper;
	
	
	
	
	/**
	 * 不使用锁
	 * @Title: noLock
	 * @Description: 
	 * @Author xuyou
	 * @DateTime 2020年11月21日 下午10:10:24
	 * @throws Exception
	 */
	@Transactional(rollbackFor = Exception.class) 
//	@Transactional
	public Long noLock(Integer amount) throws Exception {
		int num = productMapper.selectCount();
		log.info("开始下订单num:{}",num);
		if (num < amount) {
			throw new Exception("库存不足");
		}
		//减库存
		productMapper.noLockByDeductionOrderAmount(amount);
		Order order = new Order();
		order.setOrderStatus(1);
		order.setOrderAmount(amount);
		orderMapper.save(order);
		
		return order.getId();
	}
	
	/**
	 * 乐观锁
	 * @Title: lock1
	 * @Description: 
	 * @Author xuyou
	 * @DateTime 2020年11月21日 下午10:10:24
	 * @throws Exception
	 */
	//spring 默认回滚异常是RuntimeException异常,
	//如果抛出的Exception不会回滚数据
	//需要指定
	@Transactional(rollbackFor = Exception.class) 
//	@Transactional
	public Long lock1(Integer amount) throws Exception {
		log.info("开始下订单");
		int num = productMapper.deductionOrderAmount(amount);
		if (num == 0) {
			throw new Exception("库存不足");
		}
		Order order = new Order();
		order.setOrderStatus(1);
		order.setOrderAmount(amount);
		orderMapper.save(order);
		return order.getId();
	}
	
	
	/**
	 * 悲观锁
	 * @Title: lock2
	 * @Description: 
	 * @Author xuyou
	 * @DateTime 2020年11月21日 下午11:03:36
	 * @param amount
	 * @return
	 * @throws Exception
	 */
	@Transactional(rollbackFor = Exception.class) 
	public Long lock2(Integer amount) throws Exception {
		log.info("开始下订单,开始准备获取锁");
		int num = productMapper.selectCountForUpdate();
		log.info("开始下订单num:{}",num);
		if (num < amount) {
			throw new Exception("库存不足");
		}
		//减库存
		productMapper.noLockByDeductionOrderAmount(amount);
		Order order = new Order();
		order.setOrderStatus(1);
		order.setOrderAmount(amount);
		orderMapper.save(order);
		Thread.sleep(1000);
		log.info("开始下订单,释放锁");
		return order.getId();
	}
}
